#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/device.h>
#include <linux/sysfs.h>
#include "device_driver.h"

#define DEVICE_NAME "device_driver"
#define BUFFER_SIZE 1024

#define IOCTL_SET_DATA  _IOW(0, 0, char*)  // IOCTL命令：设置数据
#define IOCTL_GET_DATA  _IOR(0, 1, char*)  // IOCTL命令：获取数据

static char buffer[BUFFER_SIZE];  // 模拟设备的缓冲区
static int buffer_index = 0;      // 缓冲区的索引

static int my_driver_open(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "device_driver: Device opened\n");
    return 0;
}

static int my_driver_release(struct inode *inode, struct file *file)
{
    printk(KERN_INFO "device_driver: Device closed\n");
    return 0;
}

static ssize_t my_driver_read(struct file *file, char __user *buf, size_t len, loff_t *offset)
{
    int bytes_to_read = len < buffer_index ? len : buffer_index;
    if (bytes_to_read == 0) {
        printk(KERN_INFO "device_driver: No data to read\n");
        return 0; // No more data
    }

    if (copy_to_user(buf, buffer, bytes_to_read)) {
        printk(KERN_ERR "device_driver: Failed to send data to user\n");
        return -EFAULT;
    }

    printk(KERN_INFO "device_driver: Read %d bytes\n", bytes_to_read);
    buffer_index = 0;  // Reset buffer index after reading
    return bytes_to_read;
}

static ssize_t my_driver_write(struct file *file, const char __user *buf, size_t len, loff_t *offset)
{
    if (len > BUFFER_SIZE) {
        printk(KERN_ERR "device_driver: Write size exceeds buffer size\n");
        return -EINVAL;
    }

    if (copy_from_user(buffer, buf, len)) {
        printk(KERN_ERR "device_driver: Failed to receive data from user\n");
        return -EFAULT;
    }

    buffer_index = len;  // Update the buffer index with the data length
    printk(KERN_INFO "device_driver: Written %zu bytes\n", len);
    return len;
}

// IOCTL 操作函数
static long my_driver_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
        case IOCTL_SET_DATA:
            if (copy_from_user(buffer, (char *)arg, sizeof(buffer))) {
                return -EFAULT;
            }
            printk(KERN_INFO "device_driver: Set data to: %s\n", buffer);
            return 0;

        case IOCTL_GET_DATA:
            if (copy_to_user((char *)arg, buffer, buffer_index)) {
                return -EFAULT;
            }
            printk(KERN_INFO "device_driver: Get data: %s\n", buffer);
            return 0;

        default:
            return -ENOTTY;  // Unsupported command
    }
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_driver_open,
    .read = my_driver_read,
    .write = my_driver_write,
    .release = my_driver_release,
    .unlocked_ioctl = my_driver_ioctl,  // 添加 ioctl 支持
};

static struct cdev my_cdev;
static dev_t dev;
static struct class *dev_class = NULL;
static struct device *dev_device = NULL;

static int __init my_driver_init(void)
{
    int result;

    // 注册字符设备，主设备号为 0，表示自动分配
    result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
    if (result < 0) {
        printk(KERN_ERR "device_driver: Failed to register device\n");
        return result;
    }

    printk(KERN_INFO "device_driver: Major number is %d\n", MAJOR(dev));  // 打印分配的主设备号
    printk(KERN_INFO "device_driver: Minor number is %d\n", MINOR(dev));  // 打印分配的次设备号

    // 初始化并添加字符设备
    cdev_init(&my_cdev, &fops);
    result = cdev_add(&my_cdev, dev, 1);
    if (result) {
        printk(KERN_ERR "device_driver: Failed to add cdev\n");
        unregister_chrdev_region(dev, 1);
        return result;
    }

    // 继续创建设备类和设备节点的代码
    dev_class = class_create(THIS_MODULE, DEVICE_NAME);
    if (IS_ERR(dev_class)) {
        printk(KERN_ERR "device_driver: Failed to create device class\n");
        cdev_del(&my_cdev);
        unregister_chrdev_region(dev, 1);
        return PTR_ERR(dev_class);
    }

    // 创建设备节点
    dev_device = device_create(dev_class, NULL, dev, NULL, DEVICE_NAME);
    if (IS_ERR(dev_device)) {
        printk(KERN_ERR "device_driver: Failed to create device node\n");
        class_destroy(dev_class);
        cdev_del(&my_cdev);
        unregister_chrdev_region(dev, 1);
        return PTR_ERR(dev_device);
    }

    return 0;
}

static void __exit my_driver_exit(void)
{
    device_destroy(dev_class, dev);
    class_destroy(dev_class);
    cdev_del(&my_cdev);
    unregister_chrdev_region(dev, 1);
    printk(KERN_INFO "device_driver: Module unloaded\n");
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("OpenAI");
MODULE_DESCRIPTION("A simple Linux driver with ioctl support");
